#ifndef QQTGPIOCONTROLER_H
#define QQTGPIOCONTROLER_H

#include <QObject>
#include <QTimer>
#include <QDebug>

#include <qqtdictionary.h>

#include <qqtindustrialcontrol_global.h>

/**
 * 公开C语言接口。
 */
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_export ( unsigned int gpio );
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_unexport ( unsigned int gpio );
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_is_exported ( unsigned int gpio, bool* is_exported );

QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_configure_pin_direction ( unsigned int gpio, bool in );
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_get_pin_direction ( unsigned int gpio, bool* in );

//none, rising, falling, both
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_configure_pin_edge ( unsigned int gpio, const char* edge );
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_get_pin_edge ( unsigned int gpio, char* edge, unsigned int len );

QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_set_value ( unsigned int gpio, int value );
QQTINDUSTRIALCONTROLSHARED_EXPORT int gpio_get_value ( unsigned int gpio, int* value );

/**
 * @brief The QQtGPIOControler class
 * GPIO Controler
 *
 * C++接口
 * 操作多个PIN
 * 支持输入、输出
 * 每次操作实时更新PIN CACHE
 * 实时调试PIN
 * 支持监听？？？支持输出PWM？？？不支持。查看V2。
 *
 * 区分PIN的是PIN ID = BASE PIN ID + offset。
 *
 * 使用方法：
 * 设置BASE PIN ID，其实就是个偏移量。比如：240 【可选，默认为0】【IGNORE，取消此接口，用户输入PIN的ID的数值即可】
 * 刷新PIN列表，把系统PIN列表读到Cache。【每次刷新，Cache会被完全刷新】【开机刷新一次即可】
 * 操作PIN。导出一个PIN，关闭导出一个PIN，设置edge，设置方向，设置value。
 * 关闭导出PIN。【可选，PIN打开后，断电保持？】
 *
 * 打印PIN列表
 * 打印PIN状态。如果不存在，那么不工作。
 */
class QQTINDUSTRIALCONTROLSHARED_EXPORT QQtGPIOControler : public QObject
{
    Q_OBJECT
public:
    explicit QQtGPIOControler ( QObject* parent = 0 );
    virtual ~QQtGPIOControler();

    /**
     * !1 open pin
     */
    void export_pin ( unsigned int pinid );
    void unexport_pin ( unsigned int pinid );
    bool is_exported ( unsigned int pinid );

    /**
     * !2 configure pin
     */
    //direction
    void configure_pin_direction ( unsigned int pinid, bool in = true );
    void get_pin_direction ( unsigned int pinid, bool& in );

    /**
     * !3 set value
     */
    void set_value ( unsigned int pinid, int value );
    void get_value ( unsigned int pinid, int& value );
    int get_value ( unsigned int pinid );

public:
    QQtDictionary& pinDict();

private:
    static QQtDictionary m_pindict;
};

/**
 * @brief The QQtGPIOControlerV2 class
 * 支持设置pin edge
 * 只要Edge不是None，就会监听；每个设置获取的情形都不尽相同。
 *
 * 使用Timer管理监听；timerInterval默认为200ms，可以调整监控精度。
 * 可以实时开启关闭监听。
 */
class QQTINDUSTRIALCONTROLSHARED_EXPORT QQtGPIOControlerV2 : public QQtGPIOControler
{
    Q_OBJECT
public:
    //parent应当赋予一个能够长期存在的QObject对象。
    static QQtGPIOControlerV2* Instance ( QObject* parent = 0 );

    enum
    {
        EdgeNone,       //none      //输入 【默认】
        EdgeRising,     //rising    //中断输入，上升沿触发 【建议】
        EdgeFalling,    //falling   //中断输入，下降沿触发
        EdgeBoth,       //both      //中断输入，边沿触发
        EdgeMax
    } PinEdge;

    /**
     * !2.1 configure pin
     */
    //input edge
    void configure_pin_edge ( unsigned int pinid, int edge = EdgeNone );
    void get_pin_edge ( unsigned int pinid, int& edge );

    void setTimerInterval ( int millsecond );
    int timerInterval();

    void startListen();
    void endListen();

signals:
    void readyRead ( unsigned int pinid, int value ); //在input，监听模式下使用。

protected slots:
    void slotTimeOut();

private:
    explicit QQtGPIOControlerV2 ( QObject* parent = 0 );
    virtual ~QQtGPIOControlerV2();

    QTimer* m_timer;
};

/**
 * @brief The QQtGPIO class
 */
class QQTINDUSTRIALCONTROLSHARED_EXPORT QQtGPIO : public QObject
{
    Q_OBJECT
public:
    explicit QQtGPIO ( unsigned int pinid, QObject* parent = 0 );
    virtual ~QQtGPIO();

public:
    void export_pin();
    void unexport_pin();
    void is_exported();

    void configure_pin_direction ( bool in = true );
    void get_pin_direction ( bool& in );

    void set_value ( int value );
    void get_value ( int& value );

    void configure_pin_edge ( int edge = QQtGPIOControlerV2::EdgeNone );
    void get_pin_edge ( int& edge );

public:
    const unsigned int pinid() const;
    void set_pinid ( unsigned int pinid );

private:
    unsigned int m_pinid;
    QQtGPIOControlerV2* inst;
};

QQTINDUSTRIALCONTROLSHARED_EXPORT QDebug& operator << ( QDebug, const QQtGPIO& );


#endif //QQTGPIOCONTROLER_H
